﻿using System;
using System.Web.Security;
using Jayden.Dll.Core.Membership;
using Jayden.Dll.Web.Events;
using Jayden.Dll.Web.HtmlControls;

namespace Jayden.Dll.Web.Controls
{
	public class ForgotPasswordForm : Form
	{
		public delegate void OnUserChecked(HttpHandlerContext context, User user);
		public delegate void OnPasswordResetted(HttpHandlerContext context, User user);
		public delegate void OnPasswordChanged(HttpHandlerContext context, User user);

		public class PasswordCommandHandler : HttpCommandHandler
		{
			public PasswordCommandHandler() : this("CheckUser", "ResetPassword", "ChangePassword") { }
			public PasswordCommandHandler(string checkUserCommand, string resetPasswordCommand, string changePasswordCommand)
				: base(checkUserCommand, resetPasswordCommand, changePasswordCommand)
			{
				RegisterEvent("UserChecked");
				RegisterEvent("PasswordResetted");
				RegisterEvent("PasswordChanged");
			}
			public event OnUserChecked UserChecked { add { AddEvent<OnUserChecked>("UserChecked", value); } remove { RemoveEvent<OnUserChecked>("UserChecked", value); } }
			public event OnPasswordResetted PasswordResetted { add { AddEvent<OnPasswordResetted>("PasswordResetted", value); } remove { RemoveEvent<OnPasswordResetted>("PasswordResetted", value); } }
			public event OnPasswordChanged PasswordChanged { add { AddEvent<OnPasswordChanged>("PasswordChanged", value); } remove { RemoveEvent<OnPasswordChanged>("PasswordChanged", value); } }

			protected override void ProcessCommand(HttpHandlerContext context, string command)
			{
				if (command == "CheckUser")
				{
					string username = context.Request["username"];
					string email = context.Request["email"];
					User user = null;
					if (!string.IsNullOrWhiteSpace(email))
						username = Membership.GetUserNameByEmail(email);
					if (!string.IsNullOrWhiteSpace(username))
						user = Membership.GetUser(username) as User;
					if (user != null)
						Invoke("UserChecked", context, user);
				}
				else if (command == "ResetPassword")
				{
					long userId = long.Parse(context.Request["userId"]);
					string secretAnswer = context.Request["secretAnswer"];
					User user = Membership.GetUser(userId) as User;
					if (user != null && user.PasswordAnswer == secretAnswer)
					{
						user.Guid = Guid.NewGuid().ToString("N");
						Membership.UpdateUser(user);
						Mailer mailer = context.GetMailer(null);
						if (mailer != null)
						{
							Uri uri = new Uri(context.Request.Url);
							uri.ClearQueryString();
							uri["step"] = "3";
							uri["userId"] = user.MemberId.ToString();
							uri["guid"] = user.Guid;
							mailer.Send(new string[] { user.Email }, null, null,
								"Reset your password.",
								"You asked to reset your password : <a target=\"_blank\" href=\"" + uri.ToString(false) + "\">Click here to reset your password</a>."
							);
							Invoke("PasswordResetted", context, user);
						}
					}
				}
				else if (command == "ChangePassword")
				{
					string newPassword = context.Request["newPassword"];

					if (!string.IsNullOrWhiteSpace(newPassword))
					{
						string password = context.Request["password"];
						string userIdString = context.Request["userId"];
						User user = null;
						if (userIdString != null)
						{
							long userId = long.Parse(userIdString);
							user = Membership.GetUser(userId) as User;
						}
						else if(password != null)
						{
							user = Membership.GetUser() as User;
						}

						if (user != null)
						{
							string guid = context.Request["guid"] ?? Guid.NewGuid().ToString("N");

							if (user.Password == password || user.Guid == guid)
							{
								user.Guid = Guid.NewGuid().ToString("N");
								user.Password = newPassword;
								Membership.UpdateUser(user);
								Invoke("PasswordChanged", context, user);
							}
						}
					}
				}
			}
		}


		private Input m_Username;
		private Input m_Email;

		private Button m_CheckUser;

		private Input m_UserId;
		private Input m_SecretQuestion;
		private Input m_SecretAnswer;

		private Button m_ResetPassword;

		private Div m_PasswordDiv;
		private Input m_Password;
		private Input m_NewPassword;
		private Input m_ConfirmPassword;
		private Img m_PasswordMatch;

		private Button m_ChangePassword;

		private Fieldset[] m_Steps = new Fieldset[3];

		public override void Load(System.Xml.XmlNode node, HtmlControlLoader loader)
		{
			base.Load(node, loader);

			m_UserId = GetFormElement<Input>("userId");
			m_Username = GetFormElement<Input>("username");
			m_Email = GetFormElement<Input>("email");
			m_SecretAnswer = GetFormElement<Input>("secretAnswer");
			m_SecretQuestion = GetFormElement<Input>("secretQuestion");
			m_Password = GetFormElement<Input>("password");
			m_NewPassword = GetFormElement<Input>("newPassword");
			m_ConfirmPassword = GetElementByServerId<Input>("confirmPassword", true);
			m_PasswordDiv = GetElementByServerId<Div>("passwordDiv");
			m_PasswordMatch = GetElementByServerId<Img>("passwordMatch", true);

			m_CheckUser = GetFormElement<Button>("checkUser", "command");
			m_ResetPassword = GetFormElement<Button>("resetPassword", "command");
			m_ChangePassword = GetFormElement<Button>("changePassword", "command");

			m_Steps[0] = GetElementByServerId<Fieldset>("step1");
			m_Steps[1] = GetElementByServerId<Fieldset>("step2");
			m_Steps[2] = GetElementByServerId<Fieldset>("step3");

			m_Steps[0].ServerRender = true;
			m_Steps[1].ServerRender = false;
			m_Steps[2].ServerRender = false;
		}

		public override void ProcessHtmlRequest(HttpHandlerContext context)
		{
			PasswordCommandHandler passwordHandler = context.HandlerManager.GetHandler<PasswordCommandHandler>();
			passwordHandler.UserChecked += new OnUserChecked(UserChecked);

			if (context.Request["step"] == "3" || context.Uri["step"] == "3")
			{
				m_Steps[0].ServerRender = false;
				m_Steps[2].ServerRender = true;
				string userIdString = context.Request["userId"];
				if (userIdString != null)
				{
					long userId = long.Parse(userIdString);
					string guid = context.Request["guid"];
					User user = Membership.GetUser(userId) as User;
					if (user != null && user.Guid == guid)
					{
						m_PasswordDiv.ServerRender = false;
					}
				}
			}

			base.ProcessHtmlRequest(context);
		}

		void UserChecked(HttpHandlerContext context, User user)
		{
			m_Steps[0].ServerRender = false;
			m_Steps[1].ServerRender = true;

			m_UserId.Value = user.MemberId.ToString();
			m_SecretQuestion.Value = user.PasswordQuestion;
		}

		public override void ProcessJsRequest(HttpHandlerContext context)
		{
			base.ProcessJsRequest(context);

			string id = GetType().FullName;

			context.Js[id].AppendOnInit(@"
	var $newPassword = $('#" + m_NewPassword.Id + @"');
	var $confirmPassword = $('#" + m_ConfirmPassword.Id + @"');
	var $changePassword = $('#" + m_ChangePassword.Id + @"');
	var $passwordMatch = $('#" + m_PasswordMatch.Id + @"');
	
	var checkPasswords = function() {
		if($newPassword.val() !== '' && $newPassword.val() === $confirmPassword.val()) {
			$changePassword.removeAttr('disabled');
			$passwordMatch.attr('src', '/Images/Icons/checkmark.png').attr('alt', 'Valid').attr('title', 'The passwords match.');
		} else {
			$changePassword.attr('disabled', 'disabled');
			$passwordMatch.attr('src', '/Images/Icons/delete.png').attr('alt', 'Invalid').attr('title', 'The passwords don\'t match.');
		}
	};

	$newPassword.keyup(checkPasswords);
	$confirmPassword.keyup(checkPasswords);

	checkPasswords();
");
		}
	}
}
